package com.bzkj.basicinfo.service.impl.yxl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.bzkj.basicinfo.domain.basic.BasicStoArea;
import com.bzkj.basicinfo.domain.yxl.*;
import com.bzkj.basicinfo.domain.yxl.vo.YxlBillsListVo;
import com.bzkj.basicinfo.domain.yxl.vo.YxlBillsReceiptDetailVo;
import com.bzkj.basicinfo.domain.yxl.vo.YxlBillsReceiptVo;
import com.bzkj.basicinfo.domain.yxl.vo.YxlExportBillsListVo;
import com.bzkj.basicinfo.mapper.BasicStoAreaMapper;
import com.bzkj.basicinfo.mapper.YxlBillsMapper;
import com.bzkj.basicinfo.mapper.YxlCustomerMapper;
import com.bzkj.basicinfo.mapper.inventory.InventoryChangeMapper;
import com.bzkj.basicinfo.service.yxl.YxlBillsService;
import com.bzkj.basicinfo.utils.GenerateQRCodeUtils;
import com.bzkj.common.annotation.DataSource;
import com.bzkj.common.core.domain.AjaxResult;
import com.bzkj.common.core.domain.model.LoginUser;
import com.bzkj.common.core.page.TableDataInfo;
import com.bzkj.common.enums.DataSourceType;
import com.bzkj.common.utils.*;
import com.bzkj.framework.datasource.DynamicDataSourceContextHolder;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author：swj
 * @Desc
 * @Date：2025/7/31 9:04
 */
@Service
public class YxlBillsServiceImpl implements YxlBillsService {
    @Autowired
    private YxlBillsMapper billsMapper;

    @Autowired
    private BasicStoAreaMapper stoAreaMapper;

    @Autowired
    private YxlCustomerMapper customerMapper;

    @Override
    public List<YxlBillsList> selectBillsOutList(YxlBillsList entity) {
        // 查询出库单据列表
        List<YxlBillsList> yxlBillsLists = billsMapper.selectOutBillsList(entity);
        if (CollectionUtil.isEmpty(yxlBillsLists)) {
            return new ArrayList<>();
        }
        // 1. 先过滤出需要保留的元素（排除 billsState 为"3"或 billsID 为空的元素）
        List<YxlBillsList> filteredList = yxlBillsLists.stream()
                .filter(item -> !"3".equals(item.getBillsState()) && StringUtils.isNotBlank(item.getBillsID()))
                .collect(Collectors.toList());
        // 2. 并行处理保留的元素，添加详情列表（此时操作的是过滤后的新集合，不会修改原集合）
        filteredList.parallelStream().forEach(item -> {
            List<YxlBillsOutDetailList> outDetailLists = billsMapper.selectOutBillsDetailList(item.getBillsID());
            // 简化赋值逻辑（避免不必要的空集合创建）
            item.setOutDetailList(CollectionUtil.isNotEmpty(outDetailLists) ? outDetailLists : new ArrayList<>());
        });

        return filteredList;
    }

    @Override
    public AjaxResult selectBillsOutListByBillsId(String billsId) {
        List<HashMap<String, Object>> mapList = billsMapper.selectOutBillsListByBillsId(billsId);
        if(CollectionUtil.isEmpty(mapList)){
            return AjaxResult.success(new ArrayList<>());
        }else{
            return AjaxResult.success(mapList);
        }
    }

    @Override
    public AjaxResult selectBillsInListByBillsId(String billsId) {
        List<HashMap<String, Object>> mapList = billsMapper.selectInBillsListByBillsId(billsId);
        if(CollectionUtil.isEmpty(mapList)){
            return AjaxResult.success(new ArrayList<>());
        }else{
            return AjaxResult.success(mapList);
        }
    }

    @Override
    public TableDataInfo queryBillsOutList(YxlPrintDto entity, Integer pageNum, Integer pageSize) {
        //获取登陆用户
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        Long userId = loginUser.getUserId();
        //获取当前用户管理的仓库
//        List<String> warehouse = billsMapper.getUserManageWarehouse(userId);
        //查询单据数据
        List<YxlBillsList> billsLists = billsMapper.queryOutBillsList(entity);
        //过滤当前用户未管理的仓库数据
//        List<YxlBillsList> collect = billsLists.stream()
//                .filter(i -> i.getStoID() != null
//                        && warehouse.stream().anyMatch(w -> w != null && w.trim().equals(i.getStoID().trim())))
//                .collect(Collectors.toList());
        return DataProcessCommonUtils.getTableInfo(billsLists,pageNum,pageSize);
    }

    @Override
    public List<YxlExportBillsListVo> exportBillsOutList(YxlPrintDto entity) {
        //获取登陆用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();
        //获取当前用户管理的仓库
        List<String> warehouse = billsMapper.getUserManageWarehouse(userId);
        //查询单据数据
        List<YxlBillsList> billsLists = billsMapper.queryOutBillsList(entity);
        //过滤当前用户未管理的仓库数据
        List<YxlBillsList> collect = billsLists.stream()
                .filter(i -> i.getStoID() != null
                        && warehouse.stream().anyMatch(w -> w != null && w.trim().equals(i.getStoID().trim())))
                .collect(Collectors.toList());
        List<YxlExportBillsListVo> vos = collect.stream().map(item -> new YxlExportBillsListVo()).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(vos)){
            return vos;
        }else{
            return new ArrayList<>();
        }
    }

    @Override
    public AjaxResult queryBillsOutDetailList(YxlPrintDto entity, Integer pageNum, Integer pageSize) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        String startDate = entity.getStartDate();
        String endDate = entity.getEndDate();
        // 当日期为空时，默认设置为当前时间的前十天（字符串格式）
        if(Objects.isNull(entity.getBillsType())&&Objects.isNull(entity.getBillsID())&&Objects.isNull(entity.getBillsCD())){
            if (StringUtils.isBlank(startDate)||StringUtils.isBlank(endDate)) {
                startDate = now.minusDays(1).format(formatter);
                endDate = now.format(formatter);
                entity.setStartDate(startDate);
                entity.setEndDate(endDate);
            }
        }
        // 优化1: 批量查询汇总信息，避免N+1查询问题
        List<HashMap<String, Object>> mapList = billsMapper.queryOutBillsDetailList(entity);
        return AjaxResult.success(DataProcessCommonUtils.getTableInfo(mapList,pageNum,pageSize));
    }

    @Override
    public List<YxlBillsList> selectBillsInList(YxlBillsList entity) {
        //查询入库单据列表
        List<YxlBillsList> yxlBillsLists = billsMapper.selectInBillsList(entity);
        if (CollectionUtil.isEmpty(yxlBillsLists)) {
            return new ArrayList<>();
        }
        return yxlBillsLists;
    }

    @Override
    public List<YxlBillsInDetailList> selectBillsInDetailList(YxlPrintDto entity) {
        return billsMapper.selectInBillsDetailList(entity);
    }

    @DataSource(value = DataSourceType.SLAVE)
    @Override
    public AjaxResult printSpell(YxlPrintDto dto) {
        List<YxlPrintVo> result = new ArrayList<>();
        String num = dto.getNum();//打印数量
        String customerID = dto.getCustomerID();//单位编号
        String billsCD = dto.getBillsCD();//单位地址
        String billsID = dto.getBillsID();
        CustomerDto customerDto = new CustomerDto();
        customerDto.setDwmch(billsCD);
        customerDto.setDanwbh(customerID);
        //查询客户信息
        Customer customer = customerMapper.queryCustomer(customerDto);
        customerDto.setDjbh(billsID);
        //查询业务员
        Customer customer1 = customerMapper.queryYwyAndPsdz(customerDto);
        if(Objects.nonNull(customer)){
            String dzhdh = customer.getDzhdh();
            if(StringUtils.isNotBlank(dzhdh)){
                dzhdh = extractDetailedAddress(dzhdh);
            }
            //生成条形码
            String barCode = GenerateQRCodeUtils.createBarCode(billsID, 30, 20);
            //组装数据
            for (int i = 1; i <= Integer.parseInt(num); i++) {
                YxlPrintVo resultVo = new YxlPrintVo();
                resultVo.setBarCode(barCode);
                resultVo.setBillCode(billsID);
                resultVo.setCustomerName(customer.getDwmch()+"/"+customer.getDanwbh());
                resultVo.setAddress(dzhdh);
                if(StringUtils.isBlank(customer1.getLxrdh())){
                    resultVo.setPhone("/"+customer1.getYwy());
                }else if(StringUtils.isBlank(customer1.getYwy())){
                    resultVo.setPhone(customer1.getLxrdh()+"/");
                }else if(StringUtils.isBlank(customer1.getLxrdh())&&StringUtils.isBlank(customer1.getYwy())){
                    resultVo.setPhone("");
                }else{
                    resultVo.setPhone(customer1.getLxrdh()+"/"+customer1.getYwy());
                }
                resultVo.setDate(DateUtil.format(new Date(),"yyyy-MM-dd"));
                resultVo.setNumber(num + "-" + i);
                result.add(resultVo);
            }
        }else{
            return AjaxResult.error("没有客户信息，打印失败");
        }

        if(CollectionUtil.isNotEmpty(result)){
            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
                //将单据状态改为已打印
                billsMapper.updateOutBillsFlag(dto.getId(), "2");
                return AjaxResult.success(result);
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }else{
            return AjaxResult.error("打印失败");
        }
    }

    @Override
    public AjaxResult rejectBill(YxlPrintDto dto) {
        if(StringUtils.isBlank(dto.getId())){
            return AjaxResult.error("退回失败");
        }
        YxlPrintDto printDto = new YxlPrintDto();
        printDto.setId(dto.getId());
        printDto.setBillsState("3");
        String type = dto.getType();
        //入库
        if(type.equals("0")){
            YxlBillsList yxlBillsList = billsMapper.selectInBillById(dto.getId());
            if(yxlBillsList.getIs_qr().equals("是")){
                return AjaxResult.error("单据已确认，退回失败");
            }
            String billsID = yxlBillsList.getBillsID();
            String s = billsID + "_PC" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            printDto.setBillsID(s);
            billsMapper.updateInBill(printDto);
        }
        //出库
        if(type.equals("1")){
            YxlBillsList yxlBillsList = billsMapper.selectOutBillById(dto.getId());
            if(Objects.nonNull(yxlBillsList.getIs_qr())&&yxlBillsList.getIs_qr().equals("是")){
                return AjaxResult.error("单据已确认，退回失败");
            }
            String billsID = yxlBillsList.getBillsID();
            String s = billsID + "_PC" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            printDto.setBillsID(s);
            billsMapper.updateOutBill(printDto);
        }
        return AjaxResult.success("退回成功");
    }

    /**
     * 提取地址中最末端的详细信息
     * 匹配规则：城市/区域级地址(如XX区、XX县)之后的所有详细信息
     */
    public static String extractDetailedAddress(String address) {
        if (address == null || address.isEmpty()) {
            return "";
        }

        Pattern pattern = Pattern.compile("([^省]+?(市|区|县|市辖区|新区|旗|自治县|自治旗|特区|林区))(.*)$");
        Matcher matcher = pattern.matcher(address);

        if (matcher.find()) {
            // 提取区级单位之后的所有内容作为详细地址
            String detailedPart = matcher.group(3).trim();

            if (!detailedPart.isEmpty()) {
                return detailedPart;
            }
        }

        // 备选方案：如果未找到区级单位，尝试提取最后一个街道/路/号之后的内容
        pattern = Pattern.compile("(街道|路|道|巷|弄|号)(.*)$");
        matcher = pattern.matcher(address);
        if (matcher.find()) {
            return (matcher.group(1) + matcher.group(2)).trim();
        }

        return address;
    }

    //TODO 出库单据汇总导出
    @Override
    public AjaxResult exportOutBillList(YxlPrintDto entity, Integer pageNum, Integer pageSize) {

        return null;
    }

    @Override
    public AjaxResult exportOutBillDetailList(YxlPrintDto entity, Integer pageNum, Integer pageSize) {
        return null;
    }

    @Override
    public AjaxResult queryPdaBillsCheck(String stoId, String startDate, String endDate, String userName,String billsMode,String billsId,
                                         Integer pageNum, Integer pageSize) {
        if(StringUtils.isNotEmpty(startDate)){
            startDate = startDate+" 00:00:00";
        }
        if(StringUtils.isNotEmpty(endDate)){
            endDate = endDate+" 23:59:59";
        }
        List<HashMap<String, Object>> mapList = billsMapper.selectPdaBillsCheck(stoId, startDate, endDate, userName,billsMode,billsId);
        if (CollectionUtil.isEmpty(mapList)) {
            return AjaxResult.success(new ArrayList<>());
        }
        mapList.forEach(item->{
            if (!Objects.isNull(item.get("CheckTime"))){
                item.put("CheckTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", (Date) item.get("CheckTime")));
            }
            if(item.get("BillsMode").toString().equals("0")){
                item.put("BillsType", "销售出库");
            }
            if(item.get("BillsMode").toString().equals("2")){
                item.put("BillsType", "采购入库");
            }
        });
        return AjaxResult.success(DataProcessCommonUtils.getTableInfo(mapList, pageNum, pageSize));
    }

    @Override
    public AjaxResult queryErpJiXing() {
        return AjaxResult.success(billsMapper.selectErpJiXing());
    }

    @Override
    public AjaxResult queryJiXingMapList(String areaId) {
        // 参数校验
        if (StringUtils.isBlank(areaId)) {
            return AjaxResult.error("剂型不能为空");
        }

        BasicStoArea resultArea = new BasicStoArea();
        List<BasicStoArea> stoAreas = stoAreaMapper.selectJiXingMap(areaId);

        List<String> jxList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(stoAreas)) {
            jxList = stoAreas.stream()
                    .map(BasicStoArea::getJixing)
                    .filter(Objects::nonNull)  // 过滤空
                    .collect(Collectors.toList());
        }

        resultArea.setJxList(jxList);
        return AjaxResult.success(resultArea);
    }

    @Override
    public AjaxResult cancelCheckById(String id, String billsId) {
        if (StringUtils.isNotBlank(billsId)) {
            billsId = billsId +"_"+ DateUtils.dateTimeNow();
        }
        int i = billsMapper.cancelCheckById(id, "3", billsId);
        if (i > 0) {
            return AjaxResult.success("取消成功");
        } else {
            return AjaxResult.error("取消失败");
        }
    }

    @Override
    public AjaxResult queryErpReceipt(String billsId,String ywy,String startDate,String endDate,Integer pageNum,Integer pageSize) {
        List<HashMap<String, Object>> mapList = billsMapper.selectErpReceipt(billsId,ywy,startDate,endDate);
        return AjaxResult.success(DataProcessCommonUtils.getTableInfo(mapList, pageNum, pageSize));
    }

    @Override
    public AjaxResult queryErpReceiptDetail(String billsId) {
        return AjaxResult.success(billsMapper.selectErpReceiptDetail(billsId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult confirmReceipt(String billsId) {
        // 批量收货，spid为null表示全部
        return processReceipt(billsId, null,null,null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult confirmReceiptBySpid(String billsId, String spid,String num,String price) {
        if (spid == null || spid.trim().isEmpty()) {
            return AjaxResult.error("药品ID不能为空");
        }
        // 单品收货
        return processReceipt(billsId, spid,num,price);
    }
    /**
     * 通用收货处理方法（严格校验 + 已存在数量累加）
     * @param billsId 收货单ID
     * @param spid 单品药品ID，null表示批量收货
     * @return AjaxResult
     */
    private AjaxResult processReceipt(String billsId, String spid,String num,String price) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        // 1. 查询ERP收货主表和明细
        List<HashMap<String, Object>> erpReceipt = billsMapper.selectErpReceipt(billsId,null,null,null);
        List<HashMap<String, Object>> erpReceiptDetail = billsMapper.selectErpReceiptDetail(billsId);
        if (erpReceipt == null || erpReceipt.isEmpty()) {
            return AjaxResult.error("未查询到ERP收货主表数据");
        }
        if (erpReceiptDetail == null || erpReceiptDetail.isEmpty()) {
            return AjaxResult.error("未查询到ERP收货明细数据");
        }

        // 2. 查询WMS是否已存在该单据数据
        List<HashMap<String, Object>> wmsReceipt = billsMapper.selectWmsReceipt(billsId);
        // 如果已存在明细，按 spid 取成Map方便后面比较
        List<HashMap<String, Object>> wmsReceiptDetail = billsMapper.selectWmsReceiptDetail(billsId, spid);
        Map<String, HashMap<String, Object>> wmsDetailMap = new HashMap<>();
        if (wmsReceiptDetail != null) {
            for (HashMap<String, Object> wmsItem : wmsReceiptDetail) {
                String key = wmsItem.get("BillsID") + "_" + wmsItem.get("DrugID");
                wmsDetailMap.put(key, wmsItem);
            }
        }

        // 3. 严格校验字段及中文名
        Map<String,String> fieldNames = new LinkedHashMap<>();
        fieldNames.put("leibie","类别");
        fieldNames.put("pizhwh","批准文号");

        // 4. 过滤明细，如果spid不为空只保留对应药品
        List<HashMap<String, Object>> targetDetails = new ArrayList<>();
        for (HashMap<String, Object> item : erpReceiptDetail) {
            if (spid == null || spid.equals(String.valueOf(item.get("spid")))) {
                targetDetails.add(item);
            }
        }
        if (targetDetails.isEmpty()) {
            return AjaxResult.error(spid == null ?
                    "未找到收货明细" :
                    "未找到指定药品收货明细，spid=" + spid);
        }

        // 5. 遍历目标明细进行严格校验
        List<Map<String,Object>> validDetails = new ArrayList<>();
        List<String> errors = new ArrayList<>();
        //3.log表插入数据
        List<HashMap<String, Object>> erpReceiptLog = new ArrayList<>();
        HashMap<String, Object> logMap = new HashMap<>();
        //处理明细数据
        for (HashMap<String, Object> item : targetDetails) {
            String currentSpid = String.valueOf(item.get("spid"));
            String pizhwh = String.valueOf(item.get("pizhwh"));
            HashMap<String, Object> drugInfo = billsMapper.selectErpDrugInfo(currentSpid, pizhwh);
            if (drugInfo == null) {
                errors.add("未查询到药品信息，spid=" + currentSpid + "，pizhwh=" + pizhwh);
                continue;
            }
            List<String> itemErrors = compareFields(drugInfo, item, fieldNames, currentSpid, pizhwh);
            if (!itemErrors.isEmpty()) {
                errors.addAll(itemErrors);
                continue;
            }
            // 校验通过 → 判断WMS中是否已存在此明细，如有则累加数量
            String key =billsId + "_" +currentSpid;
            HashMap<String, Object> existing = wmsDetailMap.get(key);
            logMap.put("oldPrice", null);
            logMap.put("newPrice", null);
            logMap.put("type", "0");
            logMap.put("price",price);
            if (existing != null) {
                // 数量累加、单价、通过数量计算金额
                BigDecimal oldQty = new BigDecimal(String.valueOf(existing.get("DrugCheckNum"))).setScale(2,RoundingMode.HALF_UP);
                BigDecimal newQty = new BigDecimal(num).setScale(2,RoundingMode.HALF_UP);
                BigDecimal newDj = new BigDecimal(price).setScale(2,RoundingMode.HALF_UP);
                BigDecimal add = oldQty.add(newQty);
                if(add.compareTo(new BigDecimal(item.get("shl").toString()))>0){
                    return AjaxResult.error("超出应收数量");
                }
                //新数据的金额
                item.put("checkNum", add);
                if(!Objects.equals(item.get("dj").toString(),formatToFourDecimals(price))){
                    logMap.put("oldPrice", item.get("dj"));
                    logMap.put("newPrice", price);
                    logMap.put("type", "1");
                    item.put("dj",newDj);
                }
                if(Objects.nonNull(existing.get("ID"))){
                    item.put("id", existing.get("ID"));
                }
                if(!Objects.equals(item.get("shl"),num)){
                    logMap.put("num", num);
                    logMap.put("type", "1");
                    item.put("shl",num);
                }
            }else{
                if(!Objects.equals(item.get("dj").toString(),formatToFourDecimals(price))){
                    logMap.put("oldPrice", item.get("dj"));
                    logMap.put("newPrice", price);
                    logMap.put("type", "1");
                    item.put("dj",price);
                }
                if(!Objects.equals(item.get("shl"),num)){
                    logMap.put("num", num);
                    logMap.put("type", "1");
                    item.put("shl",num);
                }
            }
            validDetails.add(item);
        }
        logMap.put("billsId", billsId);
        logMap.put("drugId", spid);
        logMap.put("operator", username);
        logMap.put("operateTime", DateUtils.getNowDate());
        logMap.put("remark", "");
        erpReceiptLog.add(logMap);
        billsMapper.insertWmsReceiptLog(erpReceiptLog);
        // 6. 插入主表和明细表/更新已存在数量
        int mainCount = 0;
        int detailCount = 0;

        if (!validDetails.isEmpty()) {
            if (wmsReceipt == null || wmsReceipt.isEmpty()) {
                erpReceipt.forEach(item->{
                    item.put("userName",username);
                    item.put("checkDate",DateUtils.getNowDate());
                });
                // 主表不存在 → 插入主表
                mainCount = billsMapper.insertWmsReceipt(erpReceipt);
            }
            // 明细：已存在的update，新的insert
            List<Map<String,Object>> insertList = new ArrayList<>();
            List<Map<String,Object>> updateList = new ArrayList<>();

            for (Map<String,Object> item : validDetails) {
                if (item.get("id") != null) {
                    updateList.add(item);
                } else {
                    insertList.add(item);
                }
            }

            if (!insertList.isEmpty()) {
                detailCount += billsMapper.insertWmsReceiptDetail(insertList);
            }
            if (!updateList.isEmpty()) {
                detailCount += billsMapper.updateWmsReceiptDetailBatch(updateList);
            }
        }

        // 7. 返回结果
        if (!errors.isEmpty()) {
            return AjaxResult.error((spid == null ? "部分药品校验失败" : "药品收货部分校验失败") +
                    "，成功插入主表" + mainCount + "条，明细处理" + detailCount + "条；" +
                    "不合格药品：" + String.join("；", errors));
        }

        return AjaxResult.success((spid == null ? "收货成功" : "药品收货成功") +
                "：主表插入" + mainCount + "条，明细处理" + detailCount + "条");
    }

    public static String formatToFourDecimals(String numberStr) {
        try {
            // 将字符串转换为double
            double number = Double.parseDouble(numberStr);

            // 创建DecimalFormat对象，指定四位小数格式
            DecimalFormat df = new DecimalFormat("#.0000");

            // 格式化数字并返回字符串
            return df.format(number);
        } catch (NumberFormatException e) {
            // 处理转换失败的情况
            System.err.println("无效的数字格式: " + numberStr);
            return numberStr; // 或者返回其他默认值
        }
    }
    /**
     * 拒收处理方法
     * @param billsId 收货单ID
     * @param spid 单品药品ID，null表示批量拒收
     * @param num 拒收数量
     * @param price 拒收单价
     * @return AjaxResult
     */
    @Override
    public AjaxResult rejectReceiver(String billsId, String spid, String num, String price,String remark) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        // 1. 查询ERP收货主表和明细
        List<HashMap<String, Object>> erpReceipt = billsMapper.selectErpReceipt(billsId, null, null, null);
        List<HashMap<String, Object>> erpReceiptDetail = billsMapper.selectErpReceiptDetail(billsId);
        if (erpReceipt == null || erpReceipt.isEmpty()) {
            return AjaxResult.error("未查询到ERP收货主表数据");
        }
        if (erpReceiptDetail == null || erpReceiptDetail.isEmpty()) {
            return AjaxResult.error("未查询到ERP收货明细数据");
        }
        // 2. 查询WMS是否已存在该单据数据
        List<HashMap<String, Object>> wmsReceipt = billsMapper.selectWmsReceipt(billsId);
        if (wmsReceipt == null || wmsReceipt.isEmpty()) {
            erpReceipt.forEach(item -> {
                item.put("userName", username);
                item.put("checkDate", DateUtils.getNowDate());
            });
            // 主表不存在 → 插入主表
            billsMapper.insertWmsReceipt(erpReceipt);
        }
        // 查询wms是否存在明细
        List<HashMap<String, Object>> wmsReceiptDetail = billsMapper.selectWmsReceiptDetail(billsId, spid);
        if(wmsReceiptDetail == null || wmsReceiptDetail.isEmpty()) {
            //从erp明细中过滤出当前商品
            List<HashMap<String, Object>> collect = erpReceiptDetail.stream().filter(i -> i.get("spid").equals(spid)).collect(Collectors.toList());
            //明细为空，插入明细
            billsMapper.insertWmsReceiptDetail(collect);
        }
        //3.log表插入数据
        List<HashMap<String, Object>> erpReceiptLog = new ArrayList<>();
        HashMap<String, Object> logMap = new HashMap<>();
        logMap.put("billsId", billsId);
        logMap.put("drugId", spid);
        logMap.put("num", num);
        logMap.put("type", "2");
        logMap.put("oldPrice", null);
        logMap.put("newPrice", null);
        logMap.put("operator", username);
        logMap.put("operateTime", DateUtils.getNowDate());
        logMap.put("remark", remark);
        logMap.put("price", price);
        erpReceiptLog.add(logMap);
        billsMapper.insertWmsReceiptLog(erpReceiptLog);
        return AjaxResult.success("拒收成功");
    }


    @Override
    public AjaxResult queryWmsReceiptLog(String billsId, String drugId) {
        return AjaxResult.success(billsMapper.selectWmsReceiptLog(billsId,drugId));
    }

    @Override
    public AjaxResult queryWmsReceived(String billsId,String drugName,String customer,String startDate,String endDate,Integer pageNum,Integer pageSize) {
        List<HashMap<String, Object>> rows = billsMapper.selectWmsReceived(billsId, drugName,customer,startDate,endDate);

        if (rows == null || rows.isEmpty()) {
            return AjaxResult.success(Collections.emptyList());
        }

        // 按 BillsID 分组
        Map<String, YxlBillsReceiptVo> receiptMap = new LinkedHashMap<>();

        for (HashMap<String, Object> row : rows) {
            String billsIdKey = (String) row.get("BillsID");

            YxlBillsReceiptVo receipt = receiptMap.get(billsIdKey);
            if (receipt == null) {
                receipt = new YxlBillsReceiptVo();
                receipt.setBillsId(billsIdKey);
                receipt.setStoName((String) row.get("sto_name"));
                receipt.setCheckDate((String) row.get("CheckDate"));
                receipt.setReceiver((String) row.get("receiver"));
                receipt.setCustomerName((String) row.get("customer"));
                receipt.setSendDate((Date) row.get("SendDate"));
                receipt.setSendType((String) row.get("SendType"));
                receiptMap.put(billsIdKey, receipt);
            }
            // 添加明细
            if (row.get("DrugID") != null) {
                YxlBillsReceiptDetailVo detail = new YxlBillsReceiptDetailVo();
                detail.setDrugId((String) row.get("DrugID"));
                detail.setDrugName((String) row.get("DrugName"));
                detail.setDrugCD((String) row.get("DrugCD"));
                detail.setDrugDW((String) row.get("DrugDW"));
                detail.setDrugGG((String) row.get("DrugGG"));
                detail.setDrugNum(row.get("DrugNum") != null ? ((String)row.get("DrugNum")) : null);
                detail.setDrugCheckNum(row.get("DrugCheckNum") != null ? ((String)row.get("DrugCheckNum")): null);
                detail.setDrugJe(row.get("DrugJe") != null ? new BigDecimal(row.get("DrugJe").toString()) : null);
                detail.setDrugDJ(row.get("DrugDJ") != null ? new BigDecimal(row.get("DrugDJ").toString()) : null);
                detail.setDrugBatchNo((String) row.get("DrugBatchNo"));
                detail.setDrugPD((String) row.get("DrugPD"));
                detail.setDrugExp((String) row.get("DrugExp"));
                detail.setUserID((String) row.get("UserID"));
                receipt.getBillsDetail().add(detail);
            }
        }
        List<YxlBillsReceiptVo> receiptVos = new ArrayList<>(receiptMap.values());
        return AjaxResult.success(DataProcessCommonUtils.getTableInfo(receiptVos, pageNum, pageSize));
    }

    /**
     * 严格比较两个Map指定字段值是否相等（严格校验）
     */
    public static List<String> compareFields(Map<String, Object> expected,
                                             Map<String, Object> actual,
                                             Map<String, String> fieldNames,
                                             String spid,
                                             String pizhwh) {
        List<String> errors = new ArrayList<>();
        for (Map.Entry<String, String> entry : fieldNames.entrySet()) {
            String field = entry.getKey();
            String name = entry.getValue();

            Object val1 = expected.get(field);
            Object val2 = actual.get(field);

            // 严格校验：大小写敏感，不去掉空格
            if (!Objects.equals(val1, val2)) {
                errors.add("药品[spid=" + spid + ",pizhwh=" + pizhwh + "] " + name +
                        "不一致，ERP值[" + val1 + "]，明细值[" + val2 + "]");
            }
        }
        return errors;
    }

}
